#include "uwbwidget.h"
#include "tools/leiliconfig.h"
#include <QFileDialog>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkActor.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <QVTKOpenGLNativeWidget.h>
#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
#include <vtkCubeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include "views/toast.h"

#include "util/rosbag.h"

#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl_conversions/pcl_conversions.h>
#include <QEvent>
#include <QMouseEvent>
#include <QToolBar>
#include <QToolButton>
#include <QLineEdit>
#include <QHeaderView>
#include <vtkCamera.h>
#include <QDoubleSpinBox>
#include <vtkTextActor.h>
#include <vtkCallbackCommand.h>

#include <vtkCaptionActor2D.h>
#include <stdio.h>
#include <functional>
#include <QVBoxLayout>



//定义每个点的数据结构
struct VelodynePointXYZIRT
{
    PCL_ADD_POINT4D         //XYZ，PCL宏
    PCL_ADD_INTENSITY;      //反射强度，PCL宏
    uint16_t ring;          //线ID
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW    //PCL宏，确保new操作符对其操作，无须理解，用就完了
} EIGEN_ALIGN16;

//注册点类型宏
POINT_CLOUD_REGISTER_POINT_STRUCT (VelodynePointXYZIRT,
    (float, x, x) (float, y, y) (float, z, z) (float, intensity, intensity)
    (uint16_t, ring, ring)
)


// 转换为VTK格式
vtkSmartPointer<vtkPolyData> pclToVtk(const pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud) {
    auto points = vtkSmartPointer<vtkPoints>::New();
    auto vertices = vtkSmartPointer<vtkCellArray>::New();
    for (const auto& p : *cloud) {
        points->InsertNextPoint(p.x, p.y, p.z);
        vertices->InsertNextCell(1);
        vertices->InsertCellPoint(points->GetNumberOfPoints());
    }
    auto polyData = vtkSmartPointer<vtkPolyData>::New();
    polyData->SetPoints(points);
    polyData->SetVerts(vertices);
    return polyData;
}




// 用于传给回调函数的结构体定义
struct callback_args {

    PointCloudT::Ptr clicked_points_3d;
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewerPtr;

};

void handle_point_picker(vtkObject *caller, unsigned long eid, void *clientdata, void *calldata)
{
    // 将clientdata转换为QVtkDemo2类型的指针，这是一个自定义的类。
    UWBWidget* demo = (UWBWidget*)clientdata;

    // 获取当前窗口的渲染窗口。
    auto* vtkWidget = demo->getVtkWidget();
    if(!vtkWidget){
        return;
    }

    vtkRenderWindow *window = vtkWidget->renderWindow();
    if(!window)
    {
        return;
    }

    // 获取渲染窗口的第一个渲染器。
    vtkRenderer* renderer = window->GetRenderers()->GetFirstRenderer();
    if(!renderer)
    {
        return;
    }

    // 获取渲染窗口的交互器。
    vtkRenderWindowInteractor* interactor = window->GetInteractor();
    if(!interactor){
        return;
    }

    // 创建一个整型数组来存储交互器事件的位置。
    int pos[2];

    // 获取鼠标按下的屏幕坐标，单位是像素
    interactor->GetEventPosition(pos);

    // 输出事件位置到控制台。
    std::cout << "pos: " << pos[0] << " " << pos[1] << std::endl;

    // 根据鼠标选取点和容差，判断是否有三维点被选中
    int picresult = interactor->GetPicker()->Pick(pos[0], pos[1], 0, renderer);

    // 输出拾取结果到控制台。
    std::cout << "picresult: " << picresult << std::endl;

    // 如果拾取成功（picresult非零）。
    if (!picresult)
    {
        return;
    }

    // 存储拾取点的世界坐标。
    double world[3];

    // 获取拾取点的世界坐标。
    interactor->GetPicker()->GetPickPosition(world);

    // 输出拾取点的世界坐标到控制台。
    std::cout << "world: " << world[0] << " " << world[1] << " " << world[2] << std::endl;

    // 创建一个缓冲区来格式化拾取点的世界坐标。



    demo->onFreshSelectPoint(world);

}



UWBWidget::UWBWidget(QWidget *parent) : QWidget(parent)
{
    setupUI();



    m_vtkWidget->installEventFilter(this);
    this->setMouseTracking(true);

    QObject::connect(m_btnOpenPcd,&QPushButton::clicked,this,&UWBWidget::onOpenPCD);
    //connect(vtkWidget, &QVTKOpenGLNativeWidget::mousePressEvent, this, &UWBWidget::onPointSelect);

    QObject::connect(m_combox,&NumericComboBox::editTextChanged,this,&UWBWidget::onPclPointSize);
    QObject::connect(this,&UWBWidget::addSelectPoint,this,&UWBWidget::onFreshSelectPoint);

    // 添加基站选择状态管理
    m_selectedBaseStation = -1; // 初始化为未选择任何基站

    QObject::connect(m_table,&QTableWidget::cellClicked,[&](int row,int cel){
        // 设置当前选中的基站
        m_selectedBaseStation = row;

        // 更新选中状态显示
        updateBaseStationSelection();

        QWidget *wX = m_table->cellWidget(row,1);
        double x,y,z = 0;
        if(wX!= nullptr){
             if(QDoubleSpinBox* p = qobject_cast<QDoubleSpinBox*>(wX); p!= nullptr){
                   x = p->value();
            }
        }

        QWidget *wY = m_table->cellWidget(row,2);
        if(wY!= nullptr){
             if(QDoubleSpinBox* p = qobject_cast<QDoubleSpinBox*>(wY); p!= nullptr){
                    y = p->value();
            }
        }

        QWidget *wZ = m_table->cellWidget(row,3);
        if(wZ!= nullptr){
             if(QDoubleSpinBox* p = qobject_cast<QDoubleSpinBox*>(wZ); p!= nullptr){
                    z = p->value();
            }
        }

        // 设置标题表示的锚点位置为拾取点的世界坐标。
        char buffer[64];
        snprintf(buffer, sizeof(buffer), "base%d:(%0.2f, %0.2f, %0.2f)", row +1 , x, y, z);

        double pos[3] ={x,y,z};
        m_captionRepresentation->SetAnchorPosition(pos);

        m_captionWidget->GetCaptionActor2D()->GetCaptionTextProperty()->SetFontFamilyToArial();
        m_captionWidget->GetCaptionActor2D()->SetCaption(buffer);

        freshVtk();
    });
}

QVTKOpenGLNativeWidget *UWBWidget::getVtkWidget()
{
    return m_vtkWidget;
}

vtkCaptionWidget *UWBWidget::getCaptionWidget()
{
    return m_captionWidget;
}

vtkCaptionRepresentation *UWBWidget::getCaptionRepresentation()
{
    return m_captionRepresentation;
}

void UWBWidget::setupUI()
{
    setToolBar();
    QVBoxLayout *vl =new QVBoxLayout(this);
    vl->setContentsMargins(0,0,0,0);

//    m_rviz = new QRviz(this);
//    m_rviz->Display_Grid(true, "<Fixed Frame>",QColor(160,160,164));
//    m_rviz->Display_Axes(true,"<Fixed Frame>","2","0.3");

    m_vtkWidget = new QVTKOpenGLNativeWidget(this);
    auto renderer = vtkSmartPointer<vtkRenderer>::New();
    renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();

    renderWindow->AddRenderer(renderer);
    m_vtkWidget->setRenderWindow(renderWindow);

    // 创建PCL可视化器并关联渲染窗口
    viewer.reset(new pcl::visualization::PCLVisualizer(renderer,renderWindow,"viewer", false));
    viewer->setBackgroundColor(0, 0, 0);
    viewer->addCoordinateSystem(0.1);
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cloud");


    // 创建vtkCallbackCommand指针对象
    vtkNew<vtkCallbackCommand> pickCallback;
    // 设置该响应命令的客户数据入口为主程序的类
    pickCallback->SetClientData(this);
    // 设置该响应命令的具体实现函数为handle_point_picker


    pickCallback->SetCallback(handle_point_picker);

    // 定义一个与vtk窗口交互的点拾取器 vtkPointPicker
    vtkNew<vtkPointPicker> picker;
    // 设置拾取器的容差为0.005
    picker->SetTolerance(0.005);
    // 将该拾取器添加到vtk窗口交互中
    renderWindow->GetInteractor()->SetPicker(picker);
    // 定义右键按下鼠标事件的响应为前面创建的pickCallback
    renderWindow->GetInteractor()->AddObserver(vtkCommand::RightButtonPressEvent, pickCallback);

    picker->SetTolerance(0.01); // 设置选择容差
    renderWindow->GetInteractor()->SetPicker(picker);

    m_captionWidget->SetRepresentation(m_captionRepresentation);

    // 显示坐标原点
    showCoordinateOrigin();

    QWidget *w = new  QWidget(m_vtkWidget);
    QPushButton *btnConfirm = new QPushButton(w);
    btnConfirm->setObjectName("confirm");

    btnConfirm->setText("确认");
    m_table = new  QTableWidget(4, 4, w); // 创建一个4行4列的表格
    m_table->setHorizontalHeaderLabels(QStringList() << "基站ID" << "x" << "y" << "z"); // 设置水平表头
    m_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    m_table->setSelectionBehavior(QAbstractItemView::SelectRows);

    QVBoxLayout *vL = new QVBoxLayout(w);
    vL->addWidget(m_table);
    vL->addWidget(btnConfirm);
//    QHBoxLayout *hL = new QHBoxLayout(w);
//    hL->addStretch();
//    hL->addWidget(btnConfirm);
//    vL->addLayout(hL);



    for(int i = 0;  i < 4; i++){
        QTableWidgetItem *item = new QTableWidgetItem("基站" + QString::number(i+1));
        item->setFlags(item->flags() & ~Qt::ItemIsEditable);
        m_table->setItem(i, 0, item);

        for(int j = 1; j <4; j++)//列
        {
            QDoubleSpinBox *p = new QDoubleSpinBox(m_table);
            p->setMinimum(-100000.0);
            p->setDecimals(5);
            p->setValue(0);

            m_table->setCellWidget(i, j,p);

            QObject::connect(p,QOverload<double>::of(&QDoubleSpinBox::valueChanged),[=](){
                showSelectPoint();
            });
        }
    }



    //todo init table data


    m_table->setFixedHeight(180);
    m_table->setFixedWidth(480);
    m_table->setStyleSheet("QTableView::item:hover{background-color: gray;}; QTableView::item:selected{background-color: blue;}");
    auto delegate = new HoveredRowItemDelegate(m_table);
    m_table->setItemDelegate(delegate);

    //vl->addWidget(m_rviz);
    vl->addWidget(m_vtkWidget);
    vl->addWidget(m_toolBar);
}

void UWBWidget::setToolBar()
{
    // 创建一个QToolBar对象
    m_toolBar = new QToolBar(this);

    m_btnOpenPcd = new QPushButton(this);
    m_btnOpenPcd->setText("打开");
    m_btnOpenPcd->setCursor(Qt::PointingHandCursor);
    m_btnOpenPcd->setObjectName("openFile");

    m_combox = new NumericComboBox(this);
    m_combox->setFixedWidth(48);
    m_combox->setEditable(true);


    auto* p = new QPushButton(this);
    p->setText("原点");
    p->setCursor(Qt::PointingHandCursor);
    //p->setObjectName("openFile");
    QObject::connect(p,&QPushButton::clicked,this,&UWBWidget::onResetCamera);

    QStringList strList;
    strList << "1" << "2" << "3" << "4" << "5";
    m_combox->addItems(strList);
    //m_combox->setCursor(Qt::PointingHandCursor);

    m_toolBar->addWidget(m_btnOpenPcd);
    m_toolBar->addWidget(m_combox);
    m_toolBar->addWidget(p);

}

void UWBWidget::updateBaseStationSelection()
{
    // 更新表格中所有行的背景色，突出显示当前选中的基站
    for(int i = 0; i < m_table->rowCount(); i++) {
        for(int j = 0; j < m_table->columnCount(); j++) {
            QTableWidgetItem *item = m_table->item(i, j);
            if(item) {
                if(i == m_selectedBaseStation) {
                    item->setBackground(QBrush(QColor(173, 216, 230))); // 浅蓝色背景表示选中
                } else {
                    item->setBackground(QBrush(Qt::white)); // 白色背景表示未选中
                }
            }
        }
    }

    // 更新状态提示
    if(m_selectedBaseStation >= 0) {
        // 使用可用的Toast枚举值，比如Toast::Succ
        Toast::toast(Toast::Succ, QString("已选择基站%1，请在地图上点击选择坐标").arg(m_selectedBaseStation + 1), this);
    }
}

void UWBWidget::showCoordinateOrigin()
{
    // 创建坐标原点(0,0,0)的点云
    PointCloudT::Ptr origin_point(new PointCloudT);
    PointT origin(0.0, 0.0, 0.0);
    origin_point->points.push_back(origin);

    // 用黄色显示坐标原点
    pcl::visualization::PointCloudColorHandlerCustom<PointT> yellow(origin_point, 255, 255, 0);
    viewer->removePointCloud("coordinate_origin");
    viewer->addPointCloud(origin_point, yellow, "coordinate_origin");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 12, "coordinate_origin");

    // 添加坐标原点标签
    viewer->addText3D("Origin (0,0,0)", pcl::PointXYZ(0.05, 0.05, 0.05), 0.03, 1.0, 1.0, 0.0, "origin_label");

    freshVtk();
}

void UWBWidget::showSelectPoint()
{
    PointCloudT::Ptr clicked_points_3d(new PointCloudT);

    //renderer->RemoveAllViewProps();
    for(int row = 0; row < m_table->rowCount(); row++)
    {

        double pos[3];
         for(int col = 1; col < m_table->columnCount(); col++)
         {
             QWidget *w = m_table->cellWidget(row,col);
             if(w!= nullptr){
                  if(QDoubleSpinBox* p = qobject_cast<QDoubleSpinBox*>(w); p!= nullptr){
                      pos[col -1] = p->value();
                 }
             }
         }

         PointT point(pos[0],pos[1],pos[2]);
         clicked_points_3d->points.push_back(point);
    }

    // 设置屏幕渲染属性，红色显示选择的点
    pcl::visualization::PointCloudColorHandlerCustom<PointT> red(clicked_points_3d, 255, 0, 0);
    viewer->removePointCloud("clicked_points");
    viewer->addPointCloud(clicked_points_3d, red, "clicked_points");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "clicked_points");

    // 特别标记当前选中的基站
    if(m_selectedBaseStation >= 0 && m_selectedBaseStation < m_table->rowCount()) {
        double selectedPos[3];
        for(int col = 1; col < m_table->columnCount(); col++) {
            QWidget *w = m_table->cellWidget(m_selectedBaseStation, col);
            if(w != nullptr) {
                if(QDoubleSpinBox* p = qobject_cast<QDoubleSpinBox*>(w); p != nullptr) {
                    selectedPos[col - 1] = p->value();
                }
            }
        }

        // 添加特殊标记显示当前选中的基站
        PointCloudT::Ptr selected_point(new PointCloudT);
        PointT selectedPoint(selectedPos[0], selectedPos[1], selectedPos[2]);
        selected_point->points.push_back(selectedPoint);

        pcl::visualization::PointCloudColorHandlerCustom<PointT> green(selected_point, 0, 255, 0);
        viewer->removePointCloud("selected_base_station");
        viewer->addPointCloud(selected_point, green, "selected_base_station");
        viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 15, "selected_base_station");
    }
}

void UWBWidget::freshVtk()
{
    renderWindow->Render();
    m_vtkWidget->update();
    viewer->spinOnce();
}

void UWBWidget::onOpenPCD()
{
    QString fileName = QFileDialog::getOpenFileName(this, "Open Bag file", LeiliCfg->getSavePath(),
                                                    "Open PCD files(*.bag)",nullptr,QFileDialog::DontUseNativeDialog);
    if (fileName == "") return;

    QString baseName = QFileInfo(fileName).completeBaseName();

    sensor_msgs::PointCloud2 pc2;
    bool succ = RosBagSaver::readPoint2(fileName.toStdString(),pc2);

    if(!succ)
    {
        Toast::toast(Toast::Warn,QString("打开%1失败!").arg(baseName), this);
        return;
    }

    // 转换ROS消息为PCL点云
    PointCloudT::Ptr cloud(new PointCloudT);

    pcl::moveFromROSMsg(pc2, *cloud);
    pcl::visualization::PointCloudColorHandlerGenericField<PointT>fildColor(cloud, "intensity");

    // 添加点云到可视化器
    viewer->addPointCloud<PointT>(cloud, fildColor,"cloud");
    viewer->resetCamera();

    renderWindow->Render();
    m_vtkWidget->update();
    viewer->spinOnce();


    Toast::toast(Toast::Succ, QString("打开%1成功!").arg(baseName), this);

    //pointpicking();
}

void UWBWidget::onPointSelect(QMouseEvent *event)
{

}

void UWBWidget::onPclPointSize(QString size)
{
    viewer->setPointCloudRenderingProperties(
                pcl::visualization::PCL_VISUALIZER_POINT_SIZE, size.toInt(), "cloud");

    freshVtk();
}

void UWBWidget::onResetCamera()
{
    viewer->setCameraPosition(0, 0, 1, 0, 0, 0, 0, 1, 0);//俯视图

    // 更新视图
    renderWindow->Render();
    m_vtkWidget->update();
    viewer->spinOnce();
}

void UWBWidget::onFreshSelectPoint(double pos[3])
{
    // 如果没有选择基站，提示用户先选择基站
    if(m_selectedBaseStation < 0) {
        Toast::toast(Toast::Warn, "请先在表格中选择一个基站", this);
        return;
    }

    int rowNum = m_selectedBaseStation;

    char buffer[64];
    snprintf(buffer, sizeof(buffer), "base%d:(%0.2f, %0.2f, %0.2f)", rowNum+1,pos[0],pos[1],pos[2]);

    // 更新选中基站的坐标
    QWidget *wX = m_table->cellWidget(rowNum,1);
    if(wX!= nullptr){
         if(QDoubleSpinBox* p = qobject_cast<QDoubleSpinBox*>(wX); p!= nullptr){
                p->setValue(pos[0]);
        }
    }

    QWidget *wY = m_table->cellWidget(rowNum,2);
    if(wY!= nullptr){
         if(QDoubleSpinBox* p = qobject_cast<QDoubleSpinBox*>(wY); p!= nullptr){
                p->setValue(pos[1]);
        }
    }

    QWidget *wZ = m_table->cellWidget(rowNum,3);
    if(wZ!= nullptr){
         if(QDoubleSpinBox* p = qobject_cast<QDoubleSpinBox*>(wZ); p!= nullptr){
                p->setValue(pos[2]);
        }
    }

    // 设置标题表示的锚点位置为拾取点的世界坐标。
    m_captionRepresentation->SetAnchorPosition(pos);

    m_captionWidget->GetCaptionActor2D()->GetCaptionTextProperty()->SetFontFamilyToArial();
    m_captionWidget->GetCaptionActor2D()->SetCaption(buffer);

    // 设置标题控件的交互器、表示、选择性和可调整性。
    m_captionWidget->SetInteractor(m_vtkWidget->renderWindow()->GetInteractor());
    m_captionWidget->SetSelectable(0);
    m_captionWidget->SetResizable(0);
    m_captionWidget->PickingManagedOff();
    m_captionWidget->SetEnabled(1);

    // 设置标题文本的垂直和水平对齐方式。
    m_captionWidget->GetCaptionActor2D()->GetCaptionTextProperty()->SetVerticalJustificationToCentered();
    m_captionWidget->GetCaptionActor2D()->GetCaptionTextProperty()->SetJustificationToCentered();

    // 设置标题控件的边框和文本属性。
    m_captionWidget->GetCaptionActor2D()->SetBorder(1);

    // 获取openGLWidget的宽度和高度。
    int width = m_vtkWidget->width();
    int height = m_vtkWidget->height();

    // 计算拾取点在窗口中的归一化位置。
    double ratiox = (double)pos[0] / width + 0.05;
    double ratioy = (double)pos[1] / height + 0.05;

    // 输出归一化位置到控制台。
    std::cout << "ratiox: " << ratiox << " ratioy: " << ratioy << std::endl;

    // 设置标题控件边框的位置。
    m_captionWidget->GetBorderRepresentation()->SetPosition(ratiox, ratioy);
    m_captionWidget->GetBorderRepresentation()->SetPosition2(0.1, 0.05);

    // 设置标题控件的引导符号大小
    m_captionWidget->GetCaptionActor2D()->SetLeaderGlyphSize(0.01);

    // 显示成功提示
    Toast::toast(Toast::Succ, QString("基站%1坐标已更新").arg(rowNum + 1), this);

    showSelectPoint();
}

bool UWBWidget::eventFilter(QObject *object, QEvent *event)
{
     return QWidget::eventFilter(object, event);
}

HoveredRowItemDelegate::HoveredRowItemDelegate(QTableWidget *parent)
{
    tableWidget = parent;
}

void HoveredRowItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    //选中状态或是在鼠标下方的状态
    if(option.state.testFlag(QStyle::State_Selected) || option.state.testFlag(QStyle::State_MouseOver))
    {
        QTableWidgetItem *hoveredItem = tableWidget->item(index.row(), index.column());
        if(hoveredItem)
        {
            const int row = hoveredItem->row();
            //遍历列，绘制此行的所有列
            for(int column = 0; column < tableWidget->columnCount(); column++)
            {
                QTableWidgetItem *item = tableWidget->item(row, column);
                if(item)
                {
                    QModelIndex index = tableWidget->model()->index(row, column);
                    QStyleOptionViewItem itemOption = option;
                    itemOption.index = index;
                    itemOption.rect = tableWidget->visualItemRect(item);
                    QStyledItemDelegate::paint(painter, itemOption, index);
                }
            }
        }
    }
    else
    {
        return QStyledItemDelegate::paint(painter, option, index);
    }
}




























//#include "uwbwidget.h"
//#include "tools/leiliconfig.h"
//#include <QFileDialog>
//#include <QVTKOpenGLNativeWidget.h>
//#include <vtkGenericOpenGLRenderWindow.h>
//#include <vtkRenderer.h>
//#include <vtkActor.h>
//#include <vtkSphereSource.h>
//#include <vtkPolyDataMapper.h>
//#include <QVTKOpenGLNativeWidget.h>
//#include <vtkSmartPointer.h>
//#include <vtkRenderWindow.h>
//#include <vtkCubeSource.h>
//#include <vtkPolyDataMapper.h>
//#include <vtkActor.h>
//#include "views/toast.h"

//#include "util/rosbag.h"

//#include <pcl/point_cloud.h>
//#include <pcl/point_types.h>
//#include <pcl_conversions/pcl_conversions.h>
//#include <QEvent>
//#include <QMouseEvent>
//#include <QToolBar>
//#include <QToolButton>
//#include <QLineEdit>
//#include <QHeaderView>
//#include <vtkCamera.h>
//#include <QDoubleSpinBox>
//#include <vtkTextActor.h>
//#include <vtkCallbackCommand.h>

//#include <vtkCaptionActor2D.h>
//#include <stdio.h>
//#include <functional>
//#include <QVBoxLayout>



////定义每个点的数据结构
//struct VelodynePointXYZIRT
//{
//    PCL_ADD_POINT4D         //XYZ，PCL宏
//    PCL_ADD_INTENSITY;      //反射强度，PCL宏
//    uint16_t ring;          //线ID
//    EIGEN_MAKE_ALIGNED_OPERATOR_NEW    //PCL宏，确保new操作符对其操作，无须理解，用就完了
//} EIGEN_ALIGN16;

////注册点类型宏
//POINT_CLOUD_REGISTER_POINT_STRUCT (VelodynePointXYZIRT,
//    (float, x, x) (float, y, y) (float, z, z) (float, intensity, intensity)
//    (uint16_t, ring, ring)
//)


//// 转换为VTK格式
//vtkSmartPointer<vtkPolyData> pclToVtk(const pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud) {
//    auto points = vtkSmartPointer<vtkPoints>::New();
//    auto vertices = vtkSmartPointer<vtkCellArray>::New();
//    for (const auto& p : *cloud) {
//        points->InsertNextPoint(p.x, p.y, p.z);
//        vertices->InsertNextCell(1);
//        vertices->InsertCellPoint(points->GetNumberOfPoints());
//    }
//    auto polyData = vtkSmartPointer<vtkPolyData>::New();
//    polyData->SetPoints(points);
//    polyData->SetVerts(vertices);
//    return polyData;
//}




//// 用于传给回调函数的结构体定义
//struct callback_args {

//    PointCloudT::Ptr clicked_points_3d;
//    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewerPtr;

//};

//void handle_point_picker(vtkObject *caller, unsigned long eid, void *clientdata, void *calldata)
//{
//    // 将clientdata转换为QVtkDemo2类型的指针，这是一个自定义的类。
//    UWBWidget* demo = (UWBWidget*)clientdata;

//    // 获取当前窗口的渲染窗口。
//    auto* vtkWidget = demo->getVtkWidget();
//    if(!vtkWidget){
//        return;
//    }

//    vtkRenderWindow *window = vtkWidget->renderWindow();
//    if(!window)
//    {
//        return;
//    }

//    // 获取渲染窗口的第一个渲染器。
//    vtkRenderer* renderer = window->GetRenderers()->GetFirstRenderer();
//    if(!renderer)
//    {
//        return;
//    }

//    // 获取渲染窗口的交互器。
//    vtkRenderWindowInteractor* interactor = window->GetInteractor();
//    if(!interactor){
//        return;
//    }

//    // 创建一个整型数组来存储交互器事件的位置。
//    int pos[2];

//    // 获取鼠标按下的屏幕坐标，单位是像素
//    interactor->GetEventPosition(pos);

//    // 输出事件位置到控制台。
//    std::cout << "pos: " << pos[0] << " " << pos[1] << std::endl;

//    // 根据鼠标选取点和容差，判断是否有三维点被选中
//    int picresult = interactor->GetPicker()->Pick(pos[0], pos[1], 0, renderer);

//    // 输出拾取结果到控制台。
//    std::cout << "picresult: " << picresult << std::endl;

//    // 如果拾取成功（picresult非零）。
//    if (!picresult)
//    {
//        return;
//    }

//    // 存储拾取点的世界坐标。
//    double world[3];

//    // 获取拾取点的世界坐标。
//    interactor->GetPicker()->GetPickPosition(world);

//    // 输出拾取点的世界坐标到控制台。
//    std::cout << "world: " << world[0] << " " << world[1] << " " << world[2] << std::endl;

//    // 创建一个缓冲区来格式化拾取点的世界坐标。



//    demo->onFreshSelectPoint(world);

//}



//UWBWidget::UWBWidget(QWidget *parent) : QWidget(parent)
//{
//    setupUI();



//    m_vtkWidget->installEventFilter(this);
//    this->setMouseTracking(true);

//    QObject::connect(m_btnOpenPcd,&QPushButton::clicked,this,&UWBWidget::onOpenPCD);
//    //connect(vtkWidget, &QVTKOpenGLNativeWidget::mousePressEvent, this, &UWBWidget::onPointSelect);

//    QObject::connect(m_combox,&NumericComboBox::editTextChanged,this,&UWBWidget::onPclPointSize);
//    QObject::connect(this,&UWBWidget::addSelectPoint,this,&UWBWidget::onFreshSelectPoint);
//    QObject::connect(m_table,&QTableWidget::cellClicked,[&](int row,int cel){
//        QWidget *wX = m_table->cellWidget(row,1);
//        double x,y,z = 0;
//        if(wX!= nullptr){
//             if(QDoubleSpinBox* p = qobject_cast<QDoubleSpinBox*>(wX); p!= nullptr){
//                   x = p->value();
//            }
//        }

//        QWidget *wY = m_table->cellWidget(row,2);
//        if(wY!= nullptr){
//             if(QDoubleSpinBox* p = qobject_cast<QDoubleSpinBox*>(wY); p!= nullptr){
//                    y = p->value();
//            }
//        }

//        QWidget *wZ = m_table->cellWidget(row,3);
//        if(wZ!= nullptr){
//             if(QDoubleSpinBox* p = qobject_cast<QDoubleSpinBox*>(wZ); p!= nullptr){
//                    z = p->value();
//            }
//        }

//        // 设置标题表示的锚点位置为拾取点的世界坐标。
//        char buffer[64];
//        snprintf(buffer, sizeof(buffer), "base%d:(%0.2f, %0.2f, %0.2f)", row +1 , x, y, z);

//        double pos[3] ={x,y,z};
//        m_captionRepresentation->SetAnchorPosition(pos);

//        m_captionWidget->GetCaptionActor2D()->GetCaptionTextProperty()->SetFontFamilyToArial();
//        m_captionWidget->GetCaptionActor2D()->SetCaption(buffer);

//        freshVtk();
//    });
//}

//QVTKOpenGLNativeWidget *UWBWidget::getVtkWidget()
//{
//    return m_vtkWidget;
//}

//vtkCaptionWidget *UWBWidget::getCaptionWidget()
//{
//    return m_captionWidget;
//}

//vtkCaptionRepresentation *UWBWidget::getCaptionRepresentation()
//{
//    return m_captionRepresentation;
//}

//void UWBWidget::setupUI()
//{
//    setToolBar();
//    QVBoxLayout *vl =new QVBoxLayout(this);
//    vl->setContentsMargins(0,0,0,0);

////    m_rviz = new QRviz(this);
////    m_rviz->Display_Grid(true, "<Fixed Frame>",QColor(160,160,164));
////    m_rviz->Display_Axes(true,"<Fixed Frame>","2","0.3");

//    m_vtkWidget = new QVTKOpenGLNativeWidget(this);
//    auto renderer = vtkSmartPointer<vtkRenderer>::New();
//    renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();

//    renderWindow->AddRenderer(renderer);
//    m_vtkWidget->setRenderWindow(renderWindow);

//    // 创建PCL可视化器并关联渲染窗口
//    viewer.reset(new pcl::visualization::PCLVisualizer(renderer,renderWindow,"viewer", false));
//    viewer->setBackgroundColor(0, 0, 0);
//    viewer->addCoordinateSystem(0.1);
//    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cloud");


//    // 创建vtkCallbackCommand指针对象
//    vtkNew<vtkCallbackCommand> pickCallback;
//    // 设置该响应命令的客户数据入口为主程序的类
//    pickCallback->SetClientData(this);
//    // 设置该响应命令的具体实现函数为handle_point_picker


//    pickCallback->SetCallback(handle_point_picker);

//    // 定义一个与vtk窗口交互的点拾取器 vtkPointPicker
//    vtkNew<vtkPointPicker> picker;
//    // 设置拾取器的容差为0.005
//    picker->SetTolerance(0.005);
//    // 将该拾取器添加到vtk窗口交互中
//    renderWindow->GetInteractor()->SetPicker(picker);
//    // 定义右键按下鼠标事件的响应为前面创建的pickCallback
//    renderWindow->GetInteractor()->AddObserver(vtkCommand::RightButtonPressEvent, pickCallback);

//    picker->SetTolerance(0.01); // 设置选择容差
//    renderWindow->GetInteractor()->SetPicker(picker);

//    m_captionWidget->SetRepresentation(m_captionRepresentation);



//    QWidget *w = new  QWidget(m_vtkWidget);
//    QPushButton *btnConfirm = new QPushButton(w);
//    btnConfirm->setObjectName("confirm");

//    btnConfirm->setText("确认");
//    m_table = new  QTableWidget(4, 4, w); // 创建一个4行4列的表格
//    m_table->setHorizontalHeaderLabels(QStringList() << "基站ID" << "x" << "y" << "z"); // 设置水平表头
//    m_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
//    m_table->setSelectionBehavior(QAbstractItemView::SelectRows);

//    QVBoxLayout *vL = new QVBoxLayout(w);
//    vL->addWidget(m_table);
//    vL->addWidget(btnConfirm);
////    QHBoxLayout *hL = new QHBoxLayout(w);
////    hL->addStretch();
////    hL->addWidget(btnConfirm);
////    vL->addLayout(hL);



//    for(int i = 0;  i < 4; i++){
//        QTableWidgetItem *item = new QTableWidgetItem("基站" + QString::number(i+1));
//        item->setFlags(item->flags() & ~Qt::ItemIsEditable);
//        m_table->setItem(i, 0, item);

//        for(int j = 1; j <4; j++)//列
//        {
//            QDoubleSpinBox *p = new QDoubleSpinBox(m_table);
//            p->setMinimum(-100000.0);
//            p->setDecimals(5);
//            p->setValue(0);

//            m_table->setCellWidget(i, j,p);

//            QObject::connect(p,QOverload<double>::of(&QDoubleSpinBox::valueChanged),[=](){
//                showSelectPoint();
//            });
//        }
//    }



//    //todo init table data


//    m_table->setFixedHeight(180);
//    m_table->setFixedWidth(480);
//    m_table->setStyleSheet("QTableView::item:hover{background-color: gray;}; QTableView::item:selected{background-color: blue;}");
//    auto delegate = new HoveredRowItemDelegate(m_table);
//    m_table->setItemDelegate(delegate);

//    //vl->addWidget(m_rviz);
//    vl->addWidget(m_vtkWidget);
//    vl->addWidget(m_toolBar);
//}

//void UWBWidget::setToolBar()
//{
//    // 创建一个QToolBar对象
//    m_toolBar = new QToolBar(this);

//    m_btnOpenPcd = new QPushButton(this);
//    m_btnOpenPcd->setText("打开");
//    m_btnOpenPcd->setCursor(Qt::PointingHandCursor);
//    m_btnOpenPcd->setObjectName("openFile");

//    m_combox = new NumericComboBox(this);
//    m_combox->setFixedWidth(48);
//    m_combox->setEditable(true);


//    auto* p = new QPushButton(this);
//    p->setText("原点");
//    p->setCursor(Qt::PointingHandCursor);
//    //p->setObjectName("openFile");
//    QObject::connect(p,&QPushButton::clicked,this,&UWBWidget::onResetCamera);

//    QStringList strList;
//    strList << "1" << "2" << "3" << "4" << "5";
//    m_combox->addItems(strList);
//    //m_combox->setCursor(Qt::PointingHandCursor);

//    m_toolBar->addWidget(m_btnOpenPcd);
//    m_toolBar->addWidget(m_combox);
//    m_toolBar->addWidget(p);

//}

//void UWBWidget::showSelectPoint()
//{
//    PointCloudT::Ptr clicked_points_3d(new PointCloudT);

//    //renderer->RemoveAllViewProps();
//    for(int row = 0; row < m_table->rowCount(); row++)
//    {

//        double pos[3];
//         for(int col = 1; col < m_table->columnCount(); col++)
//         {
//             QWidget *w = m_table->cellWidget(row,col);
//             if(w!= nullptr){
//                  if(QDoubleSpinBox* p = qobject_cast<QDoubleSpinBox*>(w); p!= nullptr){
//                      pos[col -1] = p->value();
//                 }
//             }
//         }

//         PointT point(pos[0],pos[1],pos[2]);
//         clicked_points_3d->points.push_back(point);
//    }

//    // 设置屏幕渲染属性，红色显示选择的点
//    pcl::visualization::PointCloudColorHandlerCustom<PointT> red(clicked_points_3d, 255, 0, 0);
//    viewer->removePointCloud("clicked_points");
//    viewer->addPointCloud(clicked_points_3d, red, "clicked_points");
//    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, "clicked_points");
//}

//void UWBWidget::freshVtk()
//{
//    renderWindow->Render();
//    m_vtkWidget->update();
//    viewer->spinOnce();
//}

//void UWBWidget::onOpenPCD()
//{
//    QString fileName = QFileDialog::getOpenFileName(this, "Open Bag file", LeiliCfg->getSavePath(),
//                                                    "Open PCD files(*.bag)",nullptr,QFileDialog::DontUseNativeDialog);
//    if (fileName == "") return;

//    QString baseName = QFileInfo(fileName).completeBaseName();

//    sensor_msgs::PointCloud2 pc2;
//    bool succ = RosBagSaver::readPoint2(fileName.toStdString(),pc2);

//    if(!succ)
//    {
//        Toast::toast(Toast::Warn,QString("打开%1失败!").arg(baseName), this);
//        return;
//    }

//    // 转换ROS消息为PCL点云
//    PointCloudT::Ptr cloud(new PointCloudT);

//    pcl::moveFromROSMsg(pc2, *cloud);
//    pcl::visualization::PointCloudColorHandlerGenericField<PointT>fildColor(cloud, "intensity");

//    // 添加点云到可视化器
//    viewer->addPointCloud<PointT>(cloud, fildColor,"cloud");
//    viewer->resetCamera();

//    renderWindow->Render();
//    m_vtkWidget->update();
//    viewer->spinOnce();


//    Toast::toast(Toast::Succ, QString("打开%1成功!").arg(baseName), this);

//    //pointpicking();
//}

//void UWBWidget::onPointSelect(QMouseEvent *event)
//{

//}

//void UWBWidget::onPclPointSize(QString size)
//{
//    viewer->setPointCloudRenderingProperties(
//                pcl::visualization::PCL_VISUALIZER_POINT_SIZE, size.toInt(), "cloud");

//    freshVtk();
//}

//void UWBWidget::onResetCamera()
//{
//    viewer->setCameraPosition(0, 0, 1, 0, 0, 0, 0, 1, 0);//俯视图

//    // 更新视图
//    renderWindow->Render();
//    m_vtkWidget->update();
//    viewer->spinOnce();
//}

//void UWBWidget::onFreshSelectPoint(double pos[3])
//{
//    int rowNum = m_table->currentRow();

//    char buffer[64];
//    if(rowNum <0){
//        snprintf(buffer, sizeof(buffer), "(%0.2f, %0.2f, %0.2f)",pos[0],pos[1],pos[2]);
//    }else{
//        snprintf(buffer, sizeof(buffer), "base%d:(%0.2f, %0.2f, %0.2f)", rowNum+1,pos[0],pos[1],pos[2]);
//    }


//    QWidget *wX = m_table->cellWidget(rowNum,1);
//    if(wX!= nullptr){
//         if(QDoubleSpinBox* p = qobject_cast<QDoubleSpinBox*>(wX); p!= nullptr){
//                p->setValue(pos[0]);
//        }
//    }

//    QWidget *wY = m_table->cellWidget(rowNum,2);
//    if(wY!= nullptr){
//         if(QDoubleSpinBox* p = qobject_cast<QDoubleSpinBox*>(wY); p!= nullptr){
//                p->setValue(pos[1]);
//        }
//    }

//    QWidget *wZ = m_table->cellWidget(rowNum,3);
//    if(wZ!= nullptr){
//         if(QDoubleSpinBox* p = qobject_cast<QDoubleSpinBox*>(wZ); p!= nullptr){
//                p->setValue(pos[2]);
//        }
//    }

//    // 设置标题表示的锚点位置为拾取点的世界坐标。
//    m_captionRepresentation->SetAnchorPosition(pos);

//    m_captionWidget->GetCaptionActor2D()->GetCaptionTextProperty()->SetFontFamilyToArial();
//    m_captionWidget->GetCaptionActor2D()->SetCaption(buffer);

//    // 设置标题控件的交互器、表示、选择性和可调整性。
//    m_captionWidget->SetInteractor(m_vtkWidget->renderWindow()->GetInteractor());
//    m_captionWidget->SetSelectable(0);
//    m_captionWidget->SetResizable(0);
//    m_captionWidget->PickingManagedOff();
//    m_captionWidget->SetEnabled(1);

//    // 设置标题文本的垂直和水平对齐方式。
//    m_captionWidget->GetCaptionActor2D()->GetCaptionTextProperty()->SetVerticalJustificationToCentered();
//    m_captionWidget->GetCaptionActor2D()->GetCaptionTextProperty()->SetJustificationToCentered();

//    // 设置标题控件的边框和文本属性。
//    m_captionWidget->GetCaptionActor2D()->SetBorder(1);

//    // 获取openGLWidget的宽度和高度。
//    int width = m_vtkWidget->width();
//    int height = m_vtkWidget->height();

//    // 计算拾取点在窗口中的归一化位置。
//    double ratiox = (double)pos[0] / width + 0.05;
//    double ratioy = (double)pos[1] / height + 0.05;

//    // 输出归一化位置到控制台。
//    std::cout << "ratiox: " << ratiox << " ratioy: " << ratioy << std::endl;

//    // 设置标题控件边框的位置。
//    m_captionWidget->GetBorderRepresentation()->SetPosition(ratiox, ratioy);
//    m_captionWidget->GetBorderRepresentation()->SetPosition2(0.1, 0.05);

//    // 设置标题控件的引导符号大小
//    m_captionWidget->GetCaptionActor2D()->SetLeaderGlyphSize(0.01);

//    showSelectPoint();
//}

//bool UWBWidget::eventFilter(QObject *object, QEvent *event)
//{
//     return QWidget::eventFilter(object, event);
//}

//HoveredRowItemDelegate::HoveredRowItemDelegate(QTableWidget *parent)
//{
//    tableWidget = parent;
//}

//void HoveredRowItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
//{
//    //选中状态或是在鼠标下方的状态
//    if(option.state.testFlag(QStyle::State_Selected) || option.state.testFlag(QStyle::State_MouseOver))
//    {
//        QTableWidgetItem *hoveredItem = tableWidget->item(index.row(), index.column());
//        if(hoveredItem)
//        {
//            const int row = hoveredItem->row();
//            //遍历列，绘制此行的所有列
//            for(int column = 0; column < tableWidget->columnCount(); column++)
//            {
//                QTableWidgetItem *item = tableWidget->item(row, column);
//                if(item)
//                {
//                    QModelIndex index = tableWidget->model()->index(row, column);
//                    QStyleOptionViewItem itemOption = option;
//                    itemOption.index = index;
//                    itemOption.rect = tableWidget->visualItemRect(item);
//                    QStyledItemDelegate::paint(painter, itemOption, index);
//                }
//            }
//        }
//    }
//    else
//    {
//        return QStyledItemDelegate::paint(painter, option, index);
//    }
//}
